#include "stdinc.h"
#include "DwarfFort/Interface.h"
#include "DwarfFort/InternalStructures.h"
#include "DwarfFort/OgreKeymap.h"
#include "Main/Logger.h"
#include "DwarfFort/StateMirror.h"

#include "AsmCall.h"







#include <OIS/OIS.h>

#include <CEGUI.h>
using namespace DwarfFort;

class Interface * Ogre::Singleton<class Interface>::ms_Singleton;

Interface::Interface(void)
:mScreen(0),mKeyboard(0),mActive(true), mStateMirror(0), mCellList(0), mMatGlossList(0)
{
}

Interface::~Interface(void)
{
	if (mStateMirror)
		delete mStateMirror;
}





void Interface::fillIconDesc(IconDesc &res,int loc)
{
	Ogre::ColourValue BG(mScreen->BackgroundColors.Red[loc],
						 mScreen->BackgroundColors.Green[loc],
						 mScreen->BackgroundColors.Blue[loc],
						 1.0f);
	Ogre::ColourValue FG(mScreen->ForegroundColors.Red[loc],
					     mScreen->ForegroundColors.Green[loc],
					     mScreen->ForegroundColors.Blue[loc],
					     1.0f);
	Ogre::Root::getSingleton().getRenderSystem()->convertColourValue(BG,&res.BGColor);
	Ogre::Root::getSingleton().getRenderSystem()->convertColourValue(FG,&res.FGColor);

	res.icon = mScreen->IconDataPointer[loc];
}

void Interface::connectToDwarfFort()
{
	mStatic = (DwarfFortStatic*)0x13814A0;//0x1276FA0;
}

void Interface::ConnectScreen()
{
	mScreen =  mStatic->screen[0];

}

void Interface::setupStaticStructures()
{
	mStatic = (DwarfFortStatic*)0x13814A0;
	mCellList =(MapCellList*)0x015C4D48;//0x014A6094; 
	mMatGlossList = (MatGlossList*)0x15C6D70;//0x014A7B00; 
}



bool Interface::DwarfFortSetup()
{
	

	FARPROC setup1 = (FARPROC)(0x005E01F0);
	
	setupStaticStructures();
	memset(&mStatic->keyMap,0,0x30);
	mStatic->gameInstance = GetModuleHandle(NULL);
	mStatic->keyMap = mStatic->keys;
	mStatic->root = mStatic;
	memset(mStatic->keys,0,0x400);
	mStatic->gameRunning = 1;
	mStatic->windowDisplayed = 1;
	mStatic->WndShown = 1;

	
/*__asm
	{
//		int 3;
		pusha;
		call [setup1];
		mov stillRunning,al;
		popa
	}*/
	
	AsmCall setup(0x005E01F0);
	char stillRunning = setup().ul; 	

	mStatic->gameRunning = stillRunning;
	if (!stillRunning) 
	{
		Main::Logger::getSingleton().logMessage(std::string("Dwarf Fort setup returned false, exiting"),std::string("Interface")); 
		return false;
	}

	// this has been created only now!
	mScreen =  mStatic->screen[0];

	mStateMirror = new StateMirror(0x013A129C);

	mStatic->loopPassed1 = 0;
	mStatic->loopPassed2 = 0;
	
	/*mActions = (ActionStruct*)0x1296DCC;
	mActionCount = 0x428;

	mStrings = (ComboString*)0x1288D54;*/

	QueryPerformanceCounter(&mStatic->mCurrentTime);
	QueryPerformanceCounter(&mStatic->mOldGameTime);
	QueryPerformanceCounter(&mStatic->mOldRenderTime);
	return true;
}

void Interface::updateTimer()
{
	QueryPerformanceCounter(&mStatic->mCurrentTime);
}

bool Interface::checkGameTimer()
{
	if ((mStatic->mCurrentTime.QuadPart <= 
		 mStatic->mOldGameTime.QuadPart + mStatic->mGameTimeStep.QuadPart) && 
		 (mStatic->unknown_flag & 2) == 0)
		return false;

	mStatic->mOldGameTime.QuadPart += mStatic->mGameTimeStep.QuadPart;
	
	if (mStatic->mCurrentTime.QuadPart > 
		mStatic->mOldGameTime.QuadPart + mStatic->mGameTimeStep.QuadPart *5)
	{
		mStatic->mOldGameTime.QuadPart = mStatic->mCurrentTime.QuadPart - mStatic->mGameTimeStep.QuadPart;
	}

	if (mStatic->unknown_flag & 2)
		mStatic->mOldGameTime.QuadPart = mStatic->mCurrentTime.QuadPart;
	
	return true;

}
bool Interface::checkRenderTimer()
{
	if (mStatic->mCurrentTime.QuadPart <= 
		mStatic->mOldRenderTime.QuadPart + mStatic->mRenderStep.QuadPart)
		return false;
	
	mStatic->mOldGameTime.QuadPart += mStatic->mRenderStep.QuadPart;

	if (mStatic->mCurrentTime.QuadPart > 
		mStatic->mOldGameTime.QuadPart + mStatic->mRenderStep.QuadPart *5)
	{
		mStatic->mOldGameTime.QuadPart = mStatic->mCurrentTime.QuadPart - mStatic->mRenderStep.QuadPart;
	}


	return true;
}

bool Interface::DwarfFortGameLoop()
{
	FARPROC loop1 = (FARPROC)(0x51E240);
	FARPROC loop2 = (FARPROC)(0x6B8A50);


	char result;
	__asm
	{
		mov esi, 0x1276FA0;
		mov edi, 0x1276FA0;
		call [loop1];
		call [loop2];
		mov result,al;
	}
	mStatic->loopPassed1 = 1;
	mStatic->loopPassed2 = 1;	
	mStateMirror->updateState();
	
	return result == 0;
}



bool Interface::keyPressed(const CEGUI::EventArgs& e)
{
	int	key = ((const CEGUI::KeyEventArgs &)e).scancode;
	int nVirtKey = DwarfFortOgreKeymap[key];
	mStatic->keyMap[nVirtKey] = 1; 
	
	for (int i = 0; i < 0x64; i++)
	{
		if (mStatic->keyMsgs[i].key) continue;
		
		mStatic->keyMsgs[i].key = nVirtKey;
		mStatic->keyMsgs[i].alt = mKeyboard->isModifierDown(OIS::Keyboard::Alt);  
		mStatic->keyMsgs[i].shift = mKeyboard->isModifierDown(OIS::Keyboard::Shift);
		mStatic->keyMsgs[i].ctrl = mKeyboard->isModifierDown(OIS::Keyboard::Ctrl);  
		break;
	}
	return true;
}



bool Interface::keyReleased(const CEGUI::EventArgs& e)
{
	int key = ((const CEGUI::KeyEventArgs &)e).scancode;
	int nVirtKey = DwarfFortOgreKeymap[key];
	mStatic->keyMap[nVirtKey] = 0;
	return true;
}



void Interface::setKeyboard(OIS::Keyboard *keyboard)
{
	mKeyboard = keyboard;
}

extern HMODULE hDLL;


extern "C"
{
 	__declspec(dllexport) SHORT __stdcall CustGetKeyState(int nVirtKey)
	{
		return Interface::getSingleton().GetKey(nVirtKey);
	}

	__declspec(dllexport) int __stdcall CustShowCursor(BOOL bShow)
	{
		return bShow ;
	}
}

void Interface::PatchGame()
{
	
	DWORD GetKeyStateAddress= 0x0096E21C;
	DWORD ShowCursorAddress =	0x0096E214;
	HRESULT result;
	DWORD oldProtect;
	
	if (hDLL == 0)
	{
		_asm
		{
			int 3;
		}
	}

	result = VirtualProtect((LPVOID)GetKeyStateAddress,4,PAGE_READWRITE,&oldProtect); 
	if (!result)
		exit(-1);
//
	*((PDWORD)GetKeyStateAddress) = (DWORD)CustGetKeyState;

	result = VirtualProtect((LPVOID)ShowCursorAddress,4,PAGE_READWRITE,&oldProtect); 
	if (!result)
		exit(-1);
//
	*((PDWORD)ShowCursorAddress) = (DWORD)CustShowCursor;

}


SHORT Interface::GetKey(int nVirtKey)
{
	if (!mKeyboard) return 0;
	
	int pressed = 0;
	for (int i = 0; i < sizeof(DwarfFortOgreKeymap)/*256*/ ; i++)
		if (DwarfFortOgreKeymap[i] == nVirtKey)
		{
			pressed = mKeyboard->isKeyDown((OIS::KeyCode)i);
			break;
		}
	if (nVirtKey == 0x0D)
	 if (pressed) mEnterPressed++;
		else mEnterNotPressed++;

	if (pressed ) return -0x8000;
	return 0;
}


bool Interface::isMapLoaded()
{
	DWORD *map = (DWORD*)0x015C4D58;
	if (*map) return true;
	return false;
}


eGameState Interface::getCurrentGameState()
{
	eGameState temp = mStateMirror->getGameState();
	return temp;
}



void Interface::registerStateListener(StateListener *listener, DwarfFort::eGameState gameState) 
{
	mStateMirror->registerStateListener(listener,gameState);


}


void Interface::unRegisterStateListener(StateListener *listener, DwarfFort::eGameState gameState)
{
	mStateMirror->unRegisterStateListener(listener,gameState);
}


